Typeclasses e Módulos (em OCaml)



Daniel Yokomizo / @dyokomizo

http://dyokomizo.github.io/talks

OCaml

  • Descendente do ML (através do Caml)
  • "Híbrida" ("O" = Objective)
  • Avaliação estrita
  • Impura, porém incentiva programação pura
  • Compilador e runtime com bom desempenho
  • Módulos de primeira classe e ordem superior

Assinaturas

Usadas para definir interfaces de módulos

        module type EQ = sig
            type t
            val eq : t * t -> bool
        end;;

Uma type class pode ser usada de maneira similar

        class EQ t where
            eq :: (t, t) -> bool

Módulos

OCaml

        module IntEQ : EQ with type t = int = struct
            type t = int
            let eq (x,y) = x == y
        end;;

Haskell

        instance EQ Int where
            eq (x, y) = x == y

Módulos adicionais

OCaml

        module IntEQMod10 : EQ with type t = int = struct
            type t = int
            let eq (x,y) = (x mod 10) == (y mod 10)
        end;;

Haskell

        newtype Mod10 = Mod10 Int
        instance EQ Mod10 where
            eq (Mod10 x,Mod10 y) = (x `mod` 10) == (y `mod` 10)

Functors

OCaml

  module PairEQ(X : EQ)(Y : EQ) : EQ with type t = X.t * Y.t = struct
      type t = X.t * Y.t
      let eq ((x1,y1),(x2,y2)) = X.eq (x1,x2) && Y.eq (y1,y2)
  end;;
  module II = PairEQ(IntEQ)(IntEQ);;

Haskell

        instance (EQ a, EQ b) => EQ (a,b) where
            eq ((x1,y1),(x2,y2)) = eq (x1,x2) && eq (y1,y2)

More Functors

OCaml

module IntEQMod(N : sig val n : int end) : EQ with type t = int = struct
    type t = int
    let eq (x,y) = (x mod N.n) == (y mod N.n)
end;;
module IntEQMod13 = IntEQMod(struct let n = 13 end);;

Haskell

        -- left as an exercise for the reader

Módulos de primeira classe

OCaml

let eqs = [(module IntEQMod(struct let n = 13 end) : EQ with type t = int)
          ;(module IntEQMod(struct let n = 17 end))];;
#   val eqs : (module EQ with type t = int) list = [<module>; <module>]
    let f p m = let module M = (val m : EQ with type t = int)
                 in M.eq p;;
    List.map (f (0, 13)) eqs;;
    - : bool list = [true; false]
    List.map (f (0, 17)) eqs;;
    - : bool list = [false; true]

Haskell

        -- left as an exercise for the reader